const protocal = {
  protocol: "json",
  version: 1,
};

const MessageType = {
  /** Indicates the message is an Invocation message and implements the {@link InvocationMessage} interface. */
  Invocation: 1,
  /** Indicates the message is a StreamItem message and implements the {@link StreamItemMessage} interface. */
  StreamItem: 2,
  /** Indicates the message is a Completion message and implements the {@link CompletionMessage} interface. */
  Completion: 3,
  /** Indicates the message is a Stream Invocation message and implements the {@link StreamInvocationMessage} interface. */
  StreamInvocation: 4,
  /** Indicates the message is a Cancel Invocation message and implements the {@link CancelInvocationMessage} interface. */
  CancelInvocation: 5,
  /** Indicates the message is a Ping message and implements the {@link PingMessage} interface. */
  Ping: 6,
  /** Indicates the message is a Close message and implements the {@link CloseMessage} interface. */
  Close: 7,
};

class Hub {
  connectionId = "";
  IsConection = false;
  methods: any = {};
  invocationId = 0;
  start(url: string) {
    uni.request({
      method: "POST",
      url: url + "/negotiate",
      success: (res: any) => {
        this.connectionId = res.data.connectionId;

        this.startSocket(url);
      },
    });
  }
  startSocket(url: string) {
    url += (url.indexOf("?") < 0 ? "?" : "&") + ("id=" + this.connectionId);
    url = url.replace(/^http/, "ws");

    uni.connectSocket({
      url: url,
    });

    uni.onSocketOpen(() => {
      this.IsConection = true;
      console.log("连接成功");
    });

    uni.onSocketMessage((res) => {

      this.receive(res);
    });
  }
  invoke(functionName: string) {
    let args: any = [];
    for (let _i = 1; _i < arguments.length; _i++) {
      args[_i - 1] = arguments[_i];
    }

    this.sendData({
      target: functionName,
      arguments: ["笑你妈呢"],
      type: MessageType.Invocation,
      invocationId: this.invocationId.toString(),
    });
    this.invocationId++;
  }
  sendData(data: any, success?: any, fail?: any, complete?: any) {
    uni.sendSocketMessage({
      data: JSON.stringify({ ...data, ...protocal }) + "", //
      success: success,
      fail: fail,
      complete: complete,
    });
  }
  receive(data: any) {
    if (data.data.length > 3) {
      data.data = data.data.replace("{}", "");
    }
    var messageDataList = data.data.split("");
    //循环处理服务端信息
    for (let serverMsg of messageDataList) {
      if (serverMsg) {
        var messageData = serverMsg.replace(new RegExp("", "gm"), "");
        var message = JSON.parse(messageData);
        switch (message.type) {
          case MessageType.Invocation:
            this.invokeClientMethod(message);
            break;
        }
      }
    }
  }
  invokeClientMethod(message: any) {
    let methods = this.methods[message.target.toLowerCase()];
    if (methods) {
      methods.forEach((m: any) => m.apply(m, message.arguments));
      if (message.invocationId) {
      } else {
        console.warn(
          `No client method with the name '${message.target}' found.`
        );
      }
    }
  }
  on(method: string, fun: Function) {
    let methodName = method.toLowerCase();
    if (this.methods[methodName]) {
      this.methods[methodName].push(fun);
    } else {
      this.methods[methodName] = [fun];
    }
  }
}

const Hubs = new Hub();

// Hubs.start("http://localhost:5045/Hubs");


export default Hubs;
